<?php

// 请求工具
namespace hamster\tools\lib;

class Hcurl
{
	/**
	 * 简单的curl
	 * @param string $url 请求地址
	 * @return bool|string
	 */
    public static function curlGet($url)
    {
        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL, $url); // 设置你需要抓取的URL
        curl_setopt($ch, CURLOPT_HEADER, 0); // 设置header
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // 0-直接输出在屏幕，1-保存到字符串中
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 禁止 cURL 验证对等证书

        $data = curl_exec($ch);
        curl_close($ch);

        return $data;
    }

	/**
	 * curl请求
	 * @param string $url 请求地址
	 * @param string $method get|post|put|delete
	 * @param array $param 请求参数
	 * @param integer $timeout 超时时间
	 * @param array $header 是否以json格式请求
	 * @return array
	 */
    public static function curlRequest($url, $method='get', $param=[], $timeout=30, $header=[])
    {
        // 初始化
        $ch = curl_init();

		curl_setopt($ch, CURLOPT_HTTPHEADER, $header);			// 设置头文件的信息作为数据流输出
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);		// 设置获取的信息以文件流的形式返回，而不是直接输出。
		curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);      // 成功连接服务器前最长等待时间，如果设置为0，则无限等待
		curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);             // curl允许执行的最长秒数，如果设置为0，则永不断开

        switch ($method) {
			case 'get':
				$url = $url . '?' . http_build_query($param);
				break;
			case 'post':
				//设置post方式提交
				curl_setopt($ch, CURLOPT_POST, 1);
				//设置post数据
				curl_setopt($ch, CURLOPT_POSTFIELDS, $param);
				break;
			case 'delete':
				curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
				$url = $url . '?' . http_build_query($param);
				break;
			case 'put':
				curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
				$url = $url . '?' . http_build_query($param);
				break;
		}

		//设置抓取的url
		curl_setopt($ch, CURLOPT_URL, $url);

        //执行命令
        $data = curl_exec($ch);

		$http_code = curl_getinfo($ch,CURLINFO_HTTP_CODE);
		$curl_errno = curl_errno($ch);
		$curl_error = curl_error($ch);

        //关闭URL请求
        curl_close($ch);

		return [
			'http_code' 	=> $http_code,
			'data' 			=> $data,
			'curl_errno' 	=> $curl_errno,
			'curl_error' 	=> $curl_error
		];
	}

    /**
     * 异步请求
     * @param string $url 请求地址
     * @param array $param 请求参数
     * @param integer $timeout 连接等待时间，非响应时间
     * @param bool $isReturn 是否返回结果
     * @return false|string|string[]
     */
    public static function sockRequest($url, $method='get', $param = [], $timeout=30, $isReturn = true)
    {
        // 解析url
        $url_pieces = parse_url($url);

        $host = $url_pieces['host'];
        if ($url_pieces['scheme'] == 'https') {
			// （如果是https地址这里的域名开头需要用ssl://）
            $hosts = 'ssl://' . $host;
            $port  = '443';
        } else {
            $hosts = $host;
            $port  = $url_pieces['port'];
        }

        $query = http_build_query($param);
        $path = $url_pieces['path'] . '?' . $query;

        // 【用fsockopen()尝试连接】
		$fp = @fsockopen($hosts, $port, $errno, $errstr, $timeout);

        if ($fp) {
            stream_set_blocking($fp, 0); // 设定socket链接为无阻塞方式（默认为阻塞）

			if ($method == 'get') {
				$head = self::_sock_get($host, $path);
			} else {
				$head = self::_sock_post($host, $path, $query);
			}

			//建立成功后，向服务器写入数据
            fwrite($fp, $head);

            if (!$isReturn) {
                // 不需要结果，直接返回请求成功
                fclose($fp);
                return 'success';
            }

            $response = '';
            while (!feof($fp)) { // 判断文件指针是否到了文件末尾
                $response .= fgets($fp, 128); // 检索HTTP状态码
            }
            fclose($fp); //关闭连接

            $responseArray = explode("\r\n", $response);
            return $responseArray;
        } else {
            //没有连接
            return "{$errstr}({$errno})";
        }
    }



	public static function _sock_get($host, $path)
	{
		$head = "GET  {$path} HTTP/1.1\r\n";
		$head .= "Host:{$host}\r\n"; // （这里的域名开头不能用ssl://）
		$head .= "Connection: Close\r\n\r\n";

		return $head;
	}

	public static function _sock_post($host, $path, $query)
	{
		$head = "POST  {$path} HTTP/1.0\r\n";
		$head .= "Host: {$host} \r\n";
		$head .= "Referer: http:// {$path}  \r\n";
		$head .= "Content-type: application/x-www-form-urlencoded\r\n";
		$head .= "Content-Length: " . strlen(trim($query)) . "\r\n";
		$head .= "\r\n";
		$head .= trim($query);

		return $head;
	}

	/**
	 * @desc  获取请求ip
	 * @param string $defaultIp 获取不到ip是返回的默认值
	 * @return mixed|string
	 */
	public static function getRequestIp($defaultIp = '')
	{
		// 获取客户端ip
		if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && !empty($_SERVER['HTTP_X_FORWARDED_FOR'])){
			$ip = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])[0];
		} elseif (isset($_SERVER['HTTP_X_REAL_IP']) && !empty($_SERVER['HTTP_X_REAL_IP'])){
			$ip = $_SERVER['HTTP_X_REAL_IP'];
		} elseif (isset($_SERVER['REMOTE_ADDR']) && !empty($_SERVER['REMOTE_ADDR'])) {
			$ip = $_SERVER['REMOTE_ADDR'];
		} else {
			$ip = $defaultIp;
		}
		return $ip;
	}
}